package besta.moon.engine.index;

import java.sql.SQLException;

import besta.moon.sql.datatype.Strings;
import besta.moon.MoonException;
import besta.moon.MoonConnection;
import besta.moon.MoonCode;
import besta.moon.engine.Database;
import besta.moon.engine.View;

public class IndexDescriptions {

    private int size;
    private IndexDescription[] data;
    private boolean hasPrimary;

    public IndexDescriptions() {
        data = new IndexDescription[4];
    }

    public final int size() {
        return size;
    }

    public final IndexDescription get(int idx) {
        if (idx >= size) {
            throw new IndexOutOfBoundsException("Column index: " + idx + ", Size: " + size);
        }
        return data[idx];
    }

    public final void add(IndexDescription descr) throws SQLException {
        if (size >= data.length) {
            resize(size << 1);
        }
        if (hasPrimary && descr.isPrimary()) {
            throw MoonException.create(MoonCode.PK_ONLYONE);
        }
        hasPrimary = descr.isPrimary();
        data[size++] = descr;
    }

    private void resize(int newSize) {
        IndexDescription[] dataNew = new IndexDescription[newSize];
        System.arraycopy(data, 0, dataNew, 0, size);
        data = dataNew;
    }

    final IndexDescription findBestMatch(Strings columns) {
        int bestFactor = Integer.MAX_VALUE;
        int bestIdx = 0;
        for (int i = 0; i < size; i++) {
            int factor = data[i].matchFactor(columns);
            if (factor == 0) {
                return data[i];
            }

            if (factor < bestFactor) {
                bestFactor = factor;
                bestIdx = i;
            }
        }
        if (bestFactor == Integer.MAX_VALUE) {
            return null;
        } else {
            return data[bestIdx];
        }
    }

    public void create(MoonConnection con, Database database, View tableView) throws Exception {
        for (int i = 0; i < size; i++) {
            data[i].create(con, database, tableView);
        }
    }

    public void drop(Database database) throws Exception {
        for (int i = 0; i < size; i++) {
            data[i].drop(database);
        }
    }

    public void close() throws Exception {
        for (int i = 0; i < size; i++) {
            data[i].close();
        }
    }

    public void add(IndexDescriptions indexes) throws SQLException {
        for (int i = 0; i < indexes.size; i++) {
            add(indexes.data[i]);
        }
    }
}
